package dyyx.util;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;

import dyyx.dto.ClassLoadInfo;

public abstract class CommUtil {
	
	
	public static final String VERSION = "20200814 0909";


	public static final String UTF8 = "utf8";

	public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

	public static final String SEP = ",";

	public static final String EMPTY = "";

	public static final String LINE = "\n";
	
	
	public static String fetchString(String str,String start,String end){
		if(str==null || start==null || end==null){
			return null;
		}
		if(start.isEmpty() || end.isEmpty()){
			return null;
		}
		//  {abc}
		int index = str.indexOf(start);
		if(index<0){
			return null;
		}
		int startLen = start.length();
		int index2 = str.indexOf(end, index+startLen);
		if(index2<=index){
			return null;
		}
		return str.substring(index+startLen, index2);
	}
	
	
	public static String subStringBefore(String str,String matchStr){
		if(str==null || str.length()<=0 || matchStr==null || matchStr.length()==0){
			return null;
		}
		
		// cat@xyz  cat
		
		int pos = str.indexOf(matchStr);
		if(pos<=0){
			return null;
		}
		
		return str.substring(0, pos);		
	}

	public static long getLong(String str) {
		if (str == null || str.length() <= 0) {
			return 0;
		}
		try {
			return Long.parseLong(str);
		} catch (Throwable e) {
			return 0;
		}

	}

	public static int getInt(String str) {
		if (str == null || str.length() <= 0) {
			return 0;
		}
		try {
			return Integer.parseInt(str);
		} catch (Throwable e) {
			return 0;
		}

	}
	
	

	public static boolean isBlank(final CharSequence cs) {
		int strLen;
		if (cs == null || (strLen = cs.length()) == 0) {
			return true;
		}
		for (int i = 0; i < strLen; i++) {
			if (!Character.isWhitespace(cs.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	public static boolean isNotBlank(final CharSequence cs) {
		return !isBlank(cs);
	}

	public static String getDateString(Date date, String format) {
		if (date == null) {
			return null;
		}
		if (isBlank(format)) {
			format = DATE_FORMAT;
		}
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			return sdf.format(date);
		} catch (Throwable e) {

			return null;
		}
	}

	public static String getDateString(Date date) {
		return getDateString(date, null);
	}

	public static String getNowDateString() {
		return getDateString(new Date(), null);
	}

	public static void doSleep(long time) {
		if (time <= 0) {
			return;
		}
		try {
			Thread.sleep(time);
		} catch (Throwable e) {
			//
		}
	}

	public static ClassLoadInfo getClassLoaderInfo(Class cls) {
		if (cls == null) {
			return null;
		}
		ClassLoadInfo info = new ClassLoadInfo();

		info.classLoaders = getClassLoaderList(cls);
		info.contextClassLoader = Thread.currentThread().getContextClassLoader();

		return info;

	}

	public static List<ClassLoader> getClassLoaderList(Class cls) {
		if (cls == null) {
			return null;
		}
		ClassLoader cl = cls.getClassLoader();
		List<ClassLoader> list = new ArrayList<ClassLoader>();
		while (cl != null) {
			list.add(cl);
			cl = cl.getParent();
		}

		return list;

	}

	public static URL getResourceUrl(String name) {
		if (name == null) {
			return null;
		}
		return CommUtil.class.getClassLoader().getResource(name);
	}

	public static URL getResourceUrl(Class cls) {
		if (cls == null) {
			return null;
		}
		String name = cls.getName().replaceAll("\\.", "/") + ".class";
		//System.out.println("name=" + name);
		return CommUtil.class.getClassLoader().getResource(name);
	}
	

	public static Enumeration<URL> getResourceUrls(String name) throws Exception{
		if (name == null) {
			return null;
		}
		return CommUtil.class.getClassLoader().getResources(name);
	}

	public static Enumeration<URL> getResourceUrls(Class cls) throws Exception{
		if (cls == null) {
			return null;
		}
		String name = cls.getName().replaceAll("\\.", "/") + ".class";
		//System.out.println("name=" + name);
		return CommUtil.class.getClassLoader().getResources(name);
	}

	public static String read(String file, String charset) throws Exception {
		byte[] bytes = readBytes(file);
		if (bytes == null || bytes.length <= 0) {
			return null;
		}
		if (charset == null) {
			charset = UTF8;
		}
		return new String(bytes, charset);
	}
	
	public static String toString(byte[]bytes)throws Exception{
		if(bytes==null || bytes.length<=0){
			return null;
		}
		return new String(bytes, UTF8);
	}
	
	public static byte[] readBytes(String file) throws Exception {
		return FileUtil.readBytes(file);
	}

	
	public static void close(Closeable obj) {
		if (obj == null) {
			return;
		}
		try {
			obj.close();
		} catch (Throwable e) {

		}
	}

	public static List<String> split(String str, String sep) {
		return split(str, sep, false);
	}

	public static List<String> split(String str, String sep, boolean ignoreEmpty) {
		if (str == null) {
			return null;
		}
		if (sep == null || EMPTY.equals(sep)) {
			sep = SEP;
		}

		List<String> list = new ArrayList<String>();
		int fromIndex = 0;

		int sepLen = sep.length();
		int pos = 0;
		String tmp = null;
		// a,b,c
		while (true) {
			pos = str.indexOf(sep, fromIndex);
			if (pos < 0) {
				list.add(str.substring(fromIndex));
				break;
			}
			tmp = str.substring(fromIndex, pos);
			if (ignoreEmpty && tmp.length() <= 0) {
				// ignore
			} else {
				list.add(tmp);
			}
			fromIndex = fromIndex + tmp.length() + sepLen;
		}
		return list;
	}

	public static String replaceAll(String str, char find, char newch) {
		if (str == null) {
			return null;
		}
		int pos = str.indexOf(find);
		if (pos < 0) {
			return str;
		}

		int num = str.length();

		StringBuilder sb = new StringBuilder(num);
		char ch = '0';
		for (int i = 0; i < num; i++) {
			ch = str.charAt(i);
			if (ch == find) {
				ch = newch;
			}
			sb.append(ch);
		}
		return sb.toString();
	}

	public static List<String> getLines(String str) {
		if (str == null) {
			return null;
		}
		return split(str, LINE);
	}

	public static BufferedReader createBufferedReader(String file, String charset) throws Exception {
		if (isBlank(charset)) {
			charset = UTF8;
		}

		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));

		return br;
	}
	
	public static BufferedReader createBufferedReader(File file, String charset) throws Exception {
		if (isBlank(charset)) {
			charset = UTF8;
		}

		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));

		return br;
	}
	
	
	
	
	public static List<String> readLines(String file, String charset,boolean ignoreBlank)throws Exception{
		BufferedReader br = null;	
		try{
			br = createBufferedReader(file,charset);
			String line = null;
			List<String> list = new ArrayList<String>();
			while((line=br.readLine())!=null){	
				if(ignoreBlank && isBlank(line)){
					// ignore
				}else{
					list.add(line);
				}	
			}	
			return list;
		}finally{
			close(br);
		}	
	}
	
	
	public static List<String> getErrorInfo(Throwable e){
		return getErrorInfo(e,7);
	}

	
	
	public static List<String> getErrorInfo(Throwable e,int max){
		//e.getCause()
		if(e==null){
			return null;
		}
		List<String> list = new ArrayList<String>();
		
		
		while(e!=null){
			list.add(e.toString());
			if(max>0 && list.size()>=max){
				break;
			}
			e = e.getCause();
		}
		
		return list;
		
	}

	/**
	 * 
	 * @param name
	 *            资源不要以 / 开头
	 * @return
	 */
	public static Properties readProperties(String name) {
		if (name == null) {
			return null;
		}

		Properties prop = new Properties();
		InputStream inStream = null;

		try {
			inStream = CommUtil.class.getClassLoader().getResourceAsStream(name);
			prop.load(inStream);
			return prop;
		} catch (Throwable e) {
			throw new RuntimeException("readProperties error,name=" + name, e);
		} finally {
			close(inStream);
		}
	}
	
	
	public static Properties readPropertiesByPath(String path) {
		if (path == null) {
			return null;
		}

		Properties prop = new Properties();
		InputStream inStream = null;

		try {
			inStream = new FileInputStream(new File(path));
			prop.load(inStream);
			return prop;
		} catch (Throwable e) {
			throw new RuntimeException("readProperties error,path=" + path, e);
		} finally {
			close(inStream);
		}
	}
	
	
	public static boolean isSymlink(File file) throws IOException {
		if (file == null){
			return false;
		}		
		File canon;
		if (file.getParent() == null) {
			canon = file;
		} else {
			File canonDir = file.getParentFile().getCanonicalFile();
			canon = new File(canonDir, file.getName());
		}
		return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
	}
	
	
	public static String urlDecode(String str){
		if(StringUtils.isBlank(str)){
			return str;
		}
		try{
			return URLDecoder.decode(str, UTF8);  
		}catch(Throwable e){
			throw new RuntimeException("urlDecode error",e);
		}
	}
	
	
	public static String pathFormat(String path){
		if(StringUtils.isBlank(path)){
			return path;
		}
		if(path.startsWith("/dubbo/") && path.contains("%")){
			return urlDecode(path);
		}
		return path;
	}
	
	public static Map<String,String> queryString2map(String str){
		if(StringUtils.isBlank(str)){
			return null;
		}
		List<String> list = CommUtil.split(str, "&");
		if(list==null || list.isEmpty()){
			return null;
		}
		Map<String,String> map = new HashMap<>();
		List<String> sublist = null;
		String key,value;
		for(String item:list){
			if(CommUtil.isBlank(item)){
				continue;
			}
			sublist = CommUtil.split(item, "=");
			if(sublist==null || sublist.size()!=2){
				continue;
			}
			key = sublist.get(0);
			value = sublist.get(1);
			if(CommUtil.isBlank(key) || CommUtil.isBlank(value)){
				continue;
			}	
			map.put(key, value);		
		}
		
		return map;
	}
	
	

}